iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
0
自我挑戰組

用Line聊天機器人串起多媒體系統系列 第 21

Day 21 : 作者嗑了什麼都給我來一點 - LINE 聊天機器人翻譯實作

  • 分享至 

  • xImage
  •  


Day 20 我們示範了在 Colab 如何以 Python 實現 Google 翻譯功能的過程,也做出一個 text_to_translate() 函數能將翻譯處理更為簡化,接下來本篇重點在於如何將包好的函數功能添加到聊天機器人理。示範的方式採用 "關鍵字"+"參數" 讓BOT能實現功能。

添加翻譯功能實作

  • 我們目前在 Flask 的 app.py 程式碼如下,還只是個 echo 鸚鵡:

    from flask import Flask, request, abort
    
    from linebot import (
        LineBotApi, WebhookHandler
    )
    from linebot.exceptions import (
        InvalidSignatureError
    )
    from linebot.models import (
        MessageEvent, TextMessage, TextSendMessage,
    )
    
    app = Flask(__name__)
    
    from config import * 
    
    line_bot_api = LineBotApi(channel_access_token)
    handler = WebhookHandler(channel_secret)
    
    
    @app.route("/callback", methods=['POST'])
    def callback():
        # get X-Line-Signature header value
        signature = request.headers['X-Line-Signature']
    
        # get request body as text
        body = request.get_data(as_text=True)
        app.logger.info("Request body: " + body)
    
        # handle webhook body
        try:
            handler.handle(body, signature)
        except InvalidSignatureError:
            print("Invalid signature. Please check your channel access token/channel secret.")
            abort(400)
    
        return 'OK'
    
    
    @handler.add(MessageEvent, message=TextMessage)
    def handle_message(event):
        if event.source.user_id =='Udeadbeefdeadbeefdeadbeefdeadbeef':
            return 'OK'
        line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text=event.message.text))
    
    
    if __name__ == "__main__":
        app.run()
    
  • 目前的專案的目錄:

  • 我們準備新增翻譯功能,最終結果程式碼如下,稍後再逐步介紹:

    from flask import Flask, request, abort
    
    from linebot import (
        LineBotApi, WebhookHandler
    )
    from linebot.exceptions import (
        InvalidSignatureError
    )
    from linebot.models import (
        MessageEvent, TextMessage, TextSendMessage
    )
    
    from googletrans import Translator # Google 翻譯模組
    
    app = Flask(__name__)
    
    from config import * 
    
    line_bot_api = LineBotApi(channel_access_token)
    handler = WebhookHandler(channel_secret)
    
    
    @app.route("/callback", methods=['POST'])
    def callback():
        # get X-Line-Signature header value
        signature = request.headers['X-Line-Signature']
    
        # get request body as text
        body = request.get_data(as_text=True)
        app.logger.info("Request body: " + body)
    
        # handle webhook body
        try:
            handler.handle(body, signature)
        except InvalidSignatureError:
            print("Invalid signature. Please check your channel access token/channel secret.")
            abort(400)
    
        return 'OK'
    
    #新增自訂translate_text()函數
    def translate_text(text,dest='en'):
        """以google翻譯將text翻譯為目標語言
    
        :param text: 要翻譯的字串,接受UTF-8編碼。
        :param dest: 要翻譯的目標語言,參閱googletrans.LANGCODES語言列表。
        """
        translator = Translator()
        result = translator.translate(text, dest).text
        return result
    
    @handler.add(MessageEvent, message=TextMessage)
    def handle_message(event):
        if event.source.user_id =='Udeadbeefdeadbeefdeadbeefdeadbeef':
            return 'OK'
        if event.message.text[:3] == "@翻英":
            content = translate_text(event.message.text[3:], "en")
            message = TextSendMessage(text=content)
            line_bot_api.reply_message(event.reply_token, message)
        if event.message.text[:3] == "@翻日":
            content = translate_text(event.message.text[3:] , "ja")
            message = TextSendMessage(text=content)
            line_bot_api.reply_message(event.reply_token, message)
        if event.message.text[:3] == "@翻中":
            content = translate_text(event.message.text[3:] , "zh-tw")
            message = TextSendMessage(text=content)
            line_bot_api.reply_message(event.reply_token, message)
        else: line_bot_api.reply_message(event.reply_token,
                                         TextSendMessage(text=event.message.text))
    
    if __name__ == "__main__":
        app.run()
    
  • 將上述程式碼複製取代原本的 app.py

  • 請將您的專案資料夾內 requirements.txt 內容新增一行 googletrans==3.0.0 ,讓 commit 至 Heroku 時由該服務安裝相關模組。

    • 補充:近期如果googletrans模組有問題,請先採用googletrans==3.1.0a0 版本待其修復,並配合修正requirements.txt 的 googletrans 模組版本調整為 googletrans==3.1.0a0
  • 在終端機 'commit' 您的檔案,提醒您需要的3行指令:

    $ git add .
    $ git commit -am "add translator func"
    $ git push heroku master
    

拆解說明

  • 我們在 app.py 新增功能,將增加先前設計的 translate_text() 函數,配合引入 googletrans.Translator 模組,您會在程式碼看到以下新增內容,全為上篇所建立的模組:
    from googletrans import Translator # Google 翻譯模組
    
    #新增自訂translate_text()函數
    def translate_text(text,dest='en'):
        """以google翻譯將text翻譯為目標語言
    
        :param text: 要翻譯的字串,接受UTF-8編碼。
        :param dest: 要翻譯的目標語言,參閱googletrans.LANGCODES語言列表。
        """
        translator = Translator()
        result = translator.translate(text, dest).text
        return result
    
    
  • handle_message()的函數之下,新增流程控制。
    • Python 的流程控制最常用的就是 if else ,也可能有更多的流程需要處理時,可以用到 if elif else,寫法參考如下:
      #當只用if時
      if 條件成立:
          執行程式
      
      #if else
      if 條件成立:
          執行程式
      else:
          執行程式
      
      #if elif else
      if A條件成立:
          執行程式
      elif B條件成立:
          執行程式
      else:
          執行程式
      
      • 值得一提的是,也有傾向流程控制只用if來撰寫程式的風格,看起來更為簡潔。
    • 接著我們來拆解,看起來目前有三個 if 內容都相似,選一個來介紹:
      if event.message.text[:3] == "@翻英":
          content = translate_text(event.message.text[3:], "en")
          message = TextSendMessage(text=content)
          line_bot_api.reply_message(event.reply_token, message)
      
      • event.message.text 是使用者從 LINE 發出的訊息文字,也是由 LINE 平台傳到 Flask 收到的內容, [:3] 代表文字從頭開始0數到3之前的內容,即使用者傳訊息的開頭前3個字是@翻英時條件成立,執行縮排內的內容。
      • translate_text() 內容為收到訊息的第4個字之後文字,參數使用 event.message.text[3:] ,存入變數content
      • 最後依照 LINE Message API 的格式,以 line_bot_api.reply_message(event.reply_token, message) 以 [POST] 方法提交給 LINE 平台處理,將處理結果回應給使用者知悉。
      • commit 到 Heroku 之後,記得測試看看成果如何喔!
  • 補充我怎麼使用此功能,自己的用法是使用時先在 LINE 打上關鍵字"@翻英"、"翻中"等,再用語音輸入內容,幾乎可以取代翻譯APP啦,可以試試看喔。

小結

本篇用加入了 Google 提供的翻譯功能 API ,使用者只要以關鍵字開頭,後續的文字就會翻英/翻日/翻中,相當便捷,也藉機說明流程控制的寫法,相望對各位後續開發有些幫助,我們下篇見。

補充

近期如果googletrans模組有問題,請先採用googletrans==3.1.0a0 版本待其修復。在此篇為requirements.txtgoogletrans==3.0.0修正為googletrans==3.1.0a0,讓 commit 至 Heroku 時由該服務安裝相關模組。


上一篇
Day 20 : 熟悉你的開發工作 - Python 函數 / 模組建立
下一篇
Day 22 : DialogFlow - 自然語言理解 NLP 強者介紹篇
系列文
用Line聊天機器人串起多媒體系統30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
NiJia
iT邦新手 5 級 ‧ 2020-09-22 12:03:33

哇!這個真的讚,有空可以分享到 Chatbot 社群上~

威利斯 iT邦研究生 1 級 ‧ 2020-09-23 14:58:08 檢舉

謝謝大大鼓勵!

0
hsuan1016
iT邦新手 5 級 ‧ 2020-12-13 21:45:04

file:///Users/tzuhsuan/Desktop/%E6%88%AA%E5%9C%96%202020-12-13%20%E4%B8%8B%E5%8D%889.06.20.png
您好 我按造您的方式在colab上執行googletrans,但出現了AttributeError: 'NoneType' object has no attribute 'group'這行字,請問您是否有相關經驗?

看更多先前的回應...收起先前的回應...
威利斯 iT邦研究生 1 級 ‧ 2020-12-13 22:45:19 檢舉

您好,這個問題太好了,這是一個原本不存在的狀況,經爬文後(將錯誤丟到stackoverflow搜尋)發現是py-googletrans模組目前仍在討論的issue,剛剛測試改使用pip install googletrans==3.1.0a0這個ALPHA版本可解。您可以使用我第20日提供的Colab,並且瀏覽該issue的討論 獲得更多資訊,順便了解在github瀏覽issue的過程喔。

hsuan1016 iT邦新手 5 級 ‧ 2020-12-13 23:38:07 檢舉

file:///Users/tzuhsuan/Desktop/%E6%88%AA%E5%9C%96%202020-12-13%20%E4%B8%8B%E5%8D%8811.35.39.png
您好,感謝您上方的解答,但我上傳資料到heroku的時候發現了錯誤,查詢資料上是說,要把git作分流才行,不知道您是否也有相關經驗,謝謝!

hsuan1016 iT邦新手 5 級 ‧ 2020-12-14 00:08:36 檢舉

file:///Users/tzuhsuan/Desktop/截圖%202020-12-14%20上午12.02.47.png
file:///var/folders/z1/s_3j4knj1h782fnl647tlr7m0000gn/T/TemporaryItems/NSIRD_screencaptureui_cQYKiT/%E6%88%AA%E5%9C%96%202020-12-14%20%E4%B8%8A%E5%8D%8812.05.59.png
file:///Users/tzuhsuan/Desktop/%E6%88%AA%E5%9C%96%202020-12-14%20%E4%B8%8A%E5%8D%8812.07.15.png
file:///Users/tzuhsuan/Desktop/%E6%88%AA%E5%9C%96%202020-12-14%20%E4%B8%8A%E5%8D%8812.08.00.png
我發現heroku裡面有提到沒有檢測到默認語言,是不是我有什麼細節上出錯了?

威利斯 iT邦研究生 1 級 ‧ 2020-12-14 00:34:49 檢舉

您好,上述兩個問題需要您正確上傳留言的圖片,您可以上傳圖片到免費圖床(Day26有介紹)或直接用Hackmd編輯區貼上圖片取得圖床網址,並以![](圖床網址)MarkDown語法顯示圖片,謝謝

hsuan1016 iT邦新手 5 級 ‧ 2020-12-14 01:01:33 檢舉

![https://imgur.com/DNlELi1]
![https://imgur.com/jHGIcDV]
![https://imgur.com/dJWwE98]
![https://imgur.com/6GrxF3W]
您好,我把程式出錯的地方都放上來,從結果來看是不是有模組沒有建立完全以及heroku與git之間傳輸有誤?謝謝

威利斯 iT邦研究生 1 級 ‧ 2020-12-14 09:27:52 檢舉

您好,分別針對問題回覆如下:

    • 這個問題的提示說明了您已經有commit同樣的內容,您可以修正以下2-4問題後再次依序執行以下3個指令試試。
      $ git add .
      $ git commit -am "make it better"
      $ git push heroku master
      
    • 這錯誤來自於Heroku還不清楚要用哪個buildpack,解法為在 Heroku 的 setting 裡,在 “Add buildpack” 選項中選擇 Python:
    • 這錯誤提示源自於您電腦是否有安裝Flask模組,指令為在終端機輸入!pip install Flask,另外因為您是佈署在Heroku伺服器,伺服器有安裝Flask即可(寫在requirements.txt),本機有無安裝倒無影響。
    • 以您目前程式寫法將第17行註解掉即可。第17行是採用Day21將有關任何登入權杖帳密資訊分離至額外的config.py檔案,而您目前的寫法是尚未檔案分離,所以將第17行註解掉即可。
hsuan1016 iT邦新手 5 級 ‧ 2020-12-14 21:41:54 檢舉

![https://imgur.com/a/Zi1svuy]
您好,已按造您的方式去處理,但heroku還是無法順利推送,是否是因為部分模組,heroku無法使用?謝謝!

威利斯 iT邦研究生 1 級 ‧ 2020-12-15 00:30:24 檢舉

查看錯誤提示中有官方的說明,也在stackoverflow查到跟您一樣的待解決提問,基於手頭資訊不夠充分還原您的問題,建議您可試著採取清除buildpack再安裝一次的動作,在終端機以heroku buildpacks:clear刪除,接著 以heroku buildpacks:set heroku/python安裝。如仍不行,先檢查您的專案資料夾是否曾執行過git init初始化指令,真的無法排除則請再創新的APP,依照Day15流程再試試看喔。

我要留言

立即登入留言